package com.lqzs.businessmanager.utils;

import androidx.annotation.NonNull;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 
 * @description 线程池帮助类
 * @email 
 * @date 2022/7/20 下午2:44
 */
public final class ThreadPoolHelper {
    private static final int POOL_KEEP_ALIVE_TIME = 60;

    private static final int PROCESSORS_NUMBER = Runtime.getRuntime().availableProcessors();
    private static final ScheduledThreadPoolExecutor IO_THREAD_POOL = new ScheduledThreadPoolExecutor(
            PROCESSORS_NUMBER + 1,
            new AppCenterThreadFactory()
    );

    private ThreadPoolHelper() {
        IO_THREAD_POOL.setMaximumPoolSize(2 * PROCESSORS_NUMBER + 1);
        IO_THREAD_POOL.setKeepAliveTime(POOL_KEEP_ALIVE_TIME, TimeUnit.SECONDS);
    }

    private static class AppCenterThreadFactory implements ThreadFactory {
        AtomicInteger threadNumber = new AtomicInteger(1);
        String namePrefix = "business-manager-pool-thread-";

        AppCenterThreadFactory() {
        }

        @Override
        public Thread newThread(Runnable runnable) {
            Thread thread = new Thread(runnable, namePrefix + threadNumber.getAndIncrement());
            if (thread.isDaemon()) {
                thread.setDaemon(false);
            }
            if (thread.getPriority() != Thread.NORM_PRIORITY) {
                thread.setPriority(Thread.NORM_PRIORITY);
            }
            return thread;
        }
    }

    /**
     * 立即执行任务
     *
     * @param runnable 要执行的 runnable 任务
     */
    public static Future execute(@NonNull Runnable runnable) {
        return IO_THREAD_POOL.submit(runnable);
    }

    /**
     * 延迟执行任务
     *
     * @param runnable 要执行的 runnable 任务
     * @param delay    延迟的毫秒
     */
    public static ScheduledFuture execute(@NonNull Runnable runnable, long delay) {
        return IO_THREAD_POOL.schedule(runnable, delay, TimeUnit.MILLISECONDS);
    }

    /**
     * 延迟执行任务
     *
     * @param runnable 要执行的 runnable 任务
     * @param delay    延迟的时间
     * @param unit     延迟的时间单位
     */
    public static ScheduledFuture execute(@NonNull Runnable runnable, long delay, TimeUnit unit) {
        return IO_THREAD_POOL.schedule(runnable, delay, unit);
    }

    /**
     * 执行任务
     *
     * @param callable 要执行的任务
     * @param timeout  超时时间，单位毫秒
     * @param <V>   返回值
     * @return  执行任务的结果
     */
    public static <V> V execute(@NonNull Callable<V> callable, long timeout) {
        V result = null;
        try {
            result = IO_THREAD_POOL.submit(() -> IO_THREAD_POOL.submit(callable).
                    get(timeout, TimeUnit.MILLISECONDS)).
                    get(timeout, TimeUnit.MILLISECONDS);
        } catch (ExecutionException | InterruptedException | TimeoutException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 执行任务
     *
     * @param callable 要执行的任务
     * @param <V>   返回值
     * @return  执行任务的结果
     */
    public static <V> V executeWaitTaskFinish(@NonNull Callable<V> callable) {
        V result = null;
        try {
            result = IO_THREAD_POOL.submit(callable).get();
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
        return result;
    }

}
